<?php if (!defined('BASEPATH')) exit('No direct script access allowed.');

/**
 * Authentication class
 *
 * @author Ali OYGUR <alioygur@gmail.com>
 */
class Auth {

	/**
	 * ci supper global
	 * @var object
	 */
	private $ci;
	
	/**
	 * Login status
	 * @var bool
	 */
	private $is_logged_in;
	
	/**
	 * User data
	 * @var object
	 */
	private $udata;
	
	/**
	 * default user role id
	 * @var int
	 */
	private $default_role = 10;
	
	/**
	 * facebook connect status
	 *
	 * @var bool
	 */
	private $fconnect = TRUE;

	/**
	 * auth errors
	 * @var array
	 */
	private $errors = array();

	public function __construct()
	{
		$this->ci = &get_instance();
		$this->ci->load->helper('security');
		
		$this->ci->load->model('user_model');
		$this->ci->load->model('user_profile_model');
		$this->ci->load->model('user_credit_model');
		
		// Iinitialize
		$this->init();
	}
	
	/**
	 * Initialize
	 */
	private function init()
	{
		// facebook connect açık ise kütüphanesini yükle
		if($this->fconnect)
		{
			// LOAD FACEBOOK LIBRARY
	        $config = array(
	            'appId' => setting('app', 'id'),
	            'secret' => setting('app', 'secret')
	        );
	
	        $this->ci->load->library('facebook/facebook', $config);
		}
		
		// set login status
		$this->_is_logged_in();
		
		if(!$this->is_logged_in())
	   	{
			$this->force_fconnect();
			$this->_is_logged_in();
		}		
		
		if($this->is_logged_in())
	   	{
			$this->udata = $this->ci->user_model->get(array('id' => $this->uid()));
		}
	}
	
	/**
	 * User ID
	 * @return int
	 */
	public function uid()
	{
		return (int)$this->ci->session->userdata('uid');	
	}
	
	/**
	 * Return current user data
	 * @param string $field 
	 * @return mixed
	 */
	public function udata($field = null)
	{
		if(!empty($field)) return $this->udata->{$field};
		
		return $this->udata;
	}
	
	/**
	 * user firstname and lastname
	 * @return string
	 */
	public function fullname()
	{
		$firstname = $this->udata('firstname');
		
		if (!empty($firstname))
			return $this->udata('firstname') . ' ' . $this->udata('lastname');

		return substr($this->udata('email'), 0, strpos($this->udata('email'), '@'));
	}

	/**
	 * Mevcut kullanıcının admin gurubunda olup olmadığını kontrol eder
	 * @return bool
	 */
	public function is_admin()
	{
		return ($this->udata('role_id') > 5)? FALSE : TRUE;
	}

	/**
	 * Login
	 * 
	 * @param string $email user email
	 * @param string $password user password
	 * @param int $role minimum user role ID
	 * @return bool
	 */
	public function login($email, $password, $role = null)
	{
		!empty($role) OR $role = $this->default_role;

		$user = $this->ci->user_model->get(array('email' => $email));
		
		if ($user !== FALSE)
		{
			if(($user->email === $email) && (do_hash($user->salt . $password) === $user->password_hash))
			{
				// check role
				if($user->role_id > $role)
				{
					$this->errors[] = 'Sizin bu sayafayı görme yetkiniz yok!';
					return FALSE;
				}
				
				$this->establish_session($user);
				$this->update_last_login($user->id);
				return TRUE;
			}
		}

		$this->errors[] = 'Yanlış Kullanıci Adı/Şifre Kombinasyonu';

		return FALSE;
	}

	/**
	 * Logout
	 */
	public function logout()
	{
		$data = array('uid' => '', 'email' => '', 'user_token' => '');

		$this->ci->session->unset_userdata($data);
	}

	/**
	 * User register
	 * 
	 * @param array $data user data
	 * @param array $options options
	 * @return int user id
	 */
	public function register($data = array(), $options = array())
	{
		$main_data    = $data['main_data'];	
		$profile_data = (isset($data['profile_data'])) ? $data['profile_data'] : array();

		// encrypting password.
		$salt = $this->generate_salt();
		
		// generate password if non exist	
		isset($main_data['password_hash']) OR $main_data['password_hash'] = $this->generate_salt();
		
		// hash password
		$main_data['password_hash'] = do_hash($salt . $main_data['password_hash']);

		$user_data = array_merge(
			array(
				'fb_user_id'    => NULL,
				'role_id'       => $this->default_role,
				'username'      => $this->generate_username($data['main_data']['email']),
				'email'         => NULL,
				'salt'          => $salt,
				'password_hash' => NULL,
				'last_ip'       => $this->ci->input->ip_address(),
				'last_login'    => date('Y-m-d H:i:s')
			), $main_data
		);
		
		$uid = $this->ci->user_model->add($user_data);
		
		// set user id for profile data
		$profile_data['user_id'] = $uid;

		// TRIGGERS
		// add user_profile table
		$this->ci->load->model('user_profile_model');
		$this->ci->user_profile_model->add($profile_data);

		// autologin after register
		if (isset($options['after_login']) && $options['after_login'])
		{
			$user = $this->ci->user_model->simple_get($uid);

			$this->establish_session($user);
		}

		return $uid;
	}
	
	/**
	 * Facebook kullanıcı bilgilerini veritabanımıza kayıt öncesine
	 * hazırlar.
	 * @param array raw data
	 * @param return array
	 */	
	public function prepare_facebook_data($data)
    {
        $result = array('main_data' => array(), 'profile_data' => array());

        // PREPARE MAIN DATA

        $result['main_data']['email'] = $data['email'];
        $result['main_data']['fb_user_id'] = $data['id'];

        // PREPARE PROFILE DATA

		if (isset($data['first_name']) && $data['first_name'] != '')
		{
            $result['profile_data']['firstname'] = $data['first_name'];
        }

		if (isset($data['last_name']) && $data['last_name'] != '')
		{
            $result['profile_data']['lastname'] = $data['last_name'];
        }

		if (isset($data['birthday']) && $data['birthday'] != '')
		{
            // FB date format MM/DD/YYYY
            // MYSQL date format YYYY-MM-DD
            // settting date format

            list($month, $day, $year) = explode('/', $data['birthday']);

            $result['profile_data']['birthday'] = "{$year}-{$month}-{$day}";
        }

		if (isset($data['gender']) && $data['gender'] != '')
		{
            $result['profile_data']['gender'] = $data['gender'] == 'male' ? 'm' : 'f';
        }

		if (isset($data['location']['name']))
		{
            $location = explode(',', $data['location']['name']);

            $result['profile_data']['town'] = isset($location[0]) ? $location[0] : null;
            $result['profile_data']['city'] = isset($location[1]) ? $location[1] : null;
        }

        return $result;
    }

    /**
     * Benzersiz bir kullanıcı adı yaratır
     * @param string email
     * @return string
     */
    public function generate_username($email)
    {
        $username = substr($email, 0, strpos($email, '@'));
		$_username = $username;

        $suffix = -1;
        do {
            if(++$suffix) $_username = $username . $suffix;
        } while ($this->ci->user_model->has(array('username' => $_username)));

        return $_username;
    }
	
	/**
	 * Check login
	 * 
	 * @return bool
	 */
	public function is_logged_in()
	{
		return $this->is_logged_in;
	}

	/**
	 * Check login
	 *
	 * @return bool
	 */
	private function _is_logged_in()
	{
		// sheck if there is any session data we can use
		if ($this->uid() && $this->ci->session->userdata('user_token'))
		{
			$user = $this->ci->user_model->simple_get($this->uid());

			if ($user !== FALSE)
			{
				// Ensure user_token is still equivalent to the SHA1 of the user_id and
				// password_hash
				if (do_hash($this->uid() . $user->password_hash) === $this->ci->session->userdata('user_token'))
				{
					$this->is_logged_in = TRUE;
					return NULL;
				}
			}
		}

		$this->is_logged_in = FALSE;
	}

	/**
	 * Require login
	 * 
	 * @param string $redirect if no login redirecting address
	 * @param string $msg message
	 * */
	public function require_login($redirect = 'user/login', $msg = 'Bu sayfayı görebilmek için giriş yapmanız gereklidir.')
	{
		if (!$this->is_logged_in())
		{
			$this->ci->session->set_userdata('redirect', current_url());
			
			$this->ci->session->set_flashdata('status', "<div class='notification info'>{$msg}</div>");
			redirect($redirect);
		}
	}

	/**
	 * Update last login details
	 *
	 * @param int $uid User ID
	 * @return void
	 * */
	public function update_last_login($uid)
	{
		$data = array('last_login' => date('Y-m-d H:i:s'), 'last_ip' => $this->ci->input->ip_address());
		$this->ci->user_model->edit($data, array('id' => $uid));
	}

	/**
	 * Check user permission access
	 *
	 * @param array $roles allowed user role ids.
	 * @return bool
	 * */
	public function check_permission($roles = array())
	{
		if (!$this->is_logged_in())
			return FALSE;

		foreach ($roles as $role)
		{
			if ($role == $this->udata('role_id'))
				return TRUE;
		}

		return FALSE;
	}
	
	/**
	 * Establish session data
	 * 
	 * @param object $user user data
	 */
	public function establish_session($user)
	{
		$this->ci->session->set_userdata(array(
			'uid' => $user->id, 
			'email' => $user->email, 
			'user_token' => do_hash($user->id . $user->password_hash))
			);
	}
	
	/**
	 * $errors dizi değişkeni içerisinde bulunan hataları.
	 * Aralarına bir ayraç koyarak ddöndürür.
	 * @param string delimiter
	 * @return string
	 */
	public function errors($delimiter = '<br />')
	{		
		if(count($this->errors) > 0)
		{
			return implode($delimiter, $this->errors);
		}
		
		return NULL;
	}
	
	/**
	 * Generate 7 char salt
	 * 
	 * @return string
	 */
	public function generate_salt()
	{
		if (!function_exists('random_string'))
		{
			$this->ci->load->helper('string');
		}

		return random_string('alnum', 7);
	}
	
	/**
	 * Force facebook login
	 * Kullanıcı daha önce bizi facebook ile bağlanmış, şimdi sitemizi ziyaret 
	 * ediyorsa ve login değilse facebook ta login ise arka planda kullanıcıyı tekrar
	 * facebook ile login ediyoruz.
	 * @return void
	 */
	private function force_fconnect()
	{
		$fb_user_id = $this->ci->facebook->getUser();
		
		if($fb_user_id)
		{
			$q = $this->ci->db->get_where('user', array('fb_user_id' => $fb_user_id));
			
			if($q->num_rows())
			{
				$user = $q->row();
				
				$this->establish_session($user);
			}
		}
	}

	/**
	 * Kullanıcının kalan kredisini döndürür.
	 * eğer bir id belirtilirse o id ye ait kredi döndürürlür.
	 * yoksa mevcut kullanıcının kredisi döndürülür.
	 * 
	 * @param int user id
	 * @return int
	 */
	public function get_credit($user_id = NULL)
	{
		$user_id = ($user_id)? $user_id : $this->uid();
		
		$credit = $this->ci->db
			->get_where('user_credit', array('user_id' => $user_id))
			->row();

		$c = (int)($credit->total - $credit->used);

		return $c;
	}
}

/* End of file Auth.php */
